package com.chuangjiangx.member.basic.ddd.domain.model;

import com.chuangjiangx.dddbase.Repository;
import com.chuangjiangx.member.basic.dao.mapper.InMbrAccountMapper;
import com.chuangjiangx.member.basic.dao.model.InMbrAccount;
import com.chuangjiangx.member.basic.dao.model.InMbrAccountExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 会员账户资源库
 */
@Component
public class MbrAccountRepository implements Repository<MbrAccount, MbrAccountId> {

    @Autowired
    private InMbrAccountMapper inMbrAccountMapper;

    @Override
    public MbrAccount fromId(MbrAccountId mbrAccountId) {
        InMbrAccount inMbrAccount = inMbrAccountMapper.selectByPrimaryKey(mbrAccountId.getId());
        return wrap(inMbrAccount);
    }

    public MbrAccount fromMemberId(MemberId memberId) {
        InMbrAccountExample example = new InMbrAccountExample();
        example.createCriteria()
                .andMemberIdEqualTo(memberId.getId());
        List<InMbrAccount> inMbrAccounts = inMbrAccountMapper.selectByExample(example);
        if (inMbrAccounts.isEmpty()) {
            return null;
        }
        return wrap(inMbrAccounts.get(0));
    }

    public void changeAvailableBalance(MbrAccount oldMbrAccount,MbrAccount newMbrAccount){
        InMbrAccountExample example = new InMbrAccountExample();
        example.createCriteria()
                .andIdEqualTo(oldMbrAccount.getId().getId())
                .andAvailableBalanceEqualTo(oldMbrAccount.getAvailableBalance());
        InMbrAccount in = unbox(newMbrAccount);
        in.setId(newMbrAccount.getId().getId());
        in.setUpdateTime(new Date());
        inMbrAccountMapper.updateByExampleSelective(in,example);
    }

    public void changeAvailableScore(MbrAccount oldMbrAccount,MbrAccount newMbrAccount){
        InMbrAccountExample example = new InMbrAccountExample();
        example.createCriteria()
                .andIdEqualTo(oldMbrAccount.getId().getId())
                .andAvailableScoreEqualTo(oldMbrAccount.getAvailableScore());
        InMbrAccount in = unbox(newMbrAccount);
        in.setId(newMbrAccount.getId().getId());
        in.setUpdateTime(new Date());
        inMbrAccountMapper.updateByExampleSelective(in,example);
    }

    @Override
    public void update(MbrAccount mbrAccount) {
        InMbrAccount in = unbox(mbrAccount);
        in.setId(mbrAccount.getId().getId());
        inMbrAccountMapper.updateByPrimaryKeySelective(in);
    }

    @Override
    public void save(MbrAccount mbrAccount) {
        InMbrAccount inMbrAccount = unbox(mbrAccount);
        inMbrAccountMapper.insertSelective(inMbrAccount);
        mbrAccount.setId(new MbrAccountId(inMbrAccount.getId()));
    }



    /**
     * 数据库对象转换成domain对象
     */
    private MbrAccount wrap(InMbrAccount in) {
        if (in == null) {
            return null;
        }
        Optional<InMbrAccount> o = Optional.of(in);
        MbrAccount mbrAccount = new MbrAccount(
                new MemberId(in.getMemberId()),
                o.map(i -> i.getAvailableScore()).orElse(0L),
                o.map(i -> i.getTotalScore()).orElse(0L),
                o.map(i -> i.getAvailableBalance()).orElse(BigDecimal.ZERO),
                o.map(i -> i.getTotalRechargeBalance()).orElse(BigDecimal.ZERO),
                o.map(i -> i.getTotalGiveBalance()).orElse(BigDecimal.ZERO),
                o.map(i -> i.getTotalConsumeCount()).orElse(0),
                in.getLastConsumeTime()
        );
        mbrAccount.setId(new MbrAccountId(in.getId()));
        return mbrAccount;
    }

    /**
     * domain对象转换成数据库对象
     */
    private InMbrAccount unbox(MbrAccount mbrAccount) {
        InMbrAccount inMbrAccount = new InMbrAccount();
        inMbrAccount.setMemberId(mbrAccount.getMemberId().getId());
        inMbrAccount.setAvailableScore(mbrAccount.getAvailableScore());
        inMbrAccount.setTotalScore(mbrAccount.getTotalScore());
        inMbrAccount.setAvailableBalance(mbrAccount.getAvailableBalance());
        inMbrAccount.setTotalRechargeBalance(mbrAccount.getTotalRechargeBalance());
        inMbrAccount.setTotalGiveBalance(mbrAccount.getTotalGiveBalance());
        inMbrAccount.setTotalConsumeCount(mbrAccount.getTotalConsumeCount());
        inMbrAccount.setLastConsumeTime(mbrAccount.getLastConsumeTime());
        return inMbrAccount;
    }

    /**
     * 根据会员id查询其账户信息
     *
     * @param memberId 会员id
     * @return 账户信息
     */
    public MbrAccount findMbrAccountByMemberId(MemberId memberId) {
        InMbrAccountExample example = new InMbrAccountExample();
        example.createCriteria().andMemberIdEqualTo(memberId.getId());
        List<InMbrAccount> list = inMbrAccountMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            return wrap(list.get(0));
        }
        return null;
    }

    public void deleteByMemberId(Long memberId) {
        MbrAccount mbrAccount = findMbrAccountByMemberId(new MemberId(memberId));
        if (mbrAccount != null) {
            inMbrAccountMapper.deleteByPrimaryKey(mbrAccount.getId().getId());
        }
    }
}
